/* 
 *  Copyright 2012 CodeMagi, Inc.
 * 
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.codemagi.taglibs.input;

import com.codemagi.util.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.jsp.*;
import org.apache.log4j.*;

/**
 *
 *  This class implements the &lt;input:doubleselect&gt; tag, which presents 
 *  two &lt;select&gt; form elements with additional JavaScript code to 
 *  transfer items from one list to another on double-click
 *
 *  @version 1.0
 *  @author August Detlefsen for CodeMagi, Inc.
 */
public class DoubleSelect extends Input {

    //set to true to view debug output     
    Logger log = Logger.getLogger(this.getClass());

    private OrderedTable options;       // what are our options? :)
    private OrderedTable dOpts;         // what options are selected

    private Map leftAttributes    = new HashMap();  //individual attributes for left side
    private Map rightAttributes   = new HashMap();  //individual attributes for right side  

    private String leftLabel;
    private String rightLabel;

    public void setOptions(OrderedTable x) {
        options = x;
    }

    public void setDefault(OrderedTable x) {
	dOpts = x;
    }

    /**
     * Sets default attributes for left and right select lists
     */
    public void setAttributes(Map x) {
	if (x != null) {
	    if (leftAttributes == null  || leftAttributes.size()  == 0) leftAttributes  = x;
	    if (rightAttributes == null || rightAttributes.size() == 0) rightAttributes = x;
	}
    }

    public void setLeftAttributes(HashMap x) {
	if (x != null) leftAttributes = x;
    }

    public void setRightAttributes(HashMap x) {
	if (x != null) rightAttributes = x;
    }

    public void setLeftLabel(String x) {
	leftLabel = x;
    }

    public void setRightLabel(String x) {
	rightLabel = x;
    }

    public int doStartTag() throws JspException {
	try {
            // sanity check
            if (name == null || name.equals("")) {
                throw new JspTagException("invalid null or empty 'name'");
	    }
	    
	    // get what we need from the page
	    ServletRequest req = pageContext.getRequest();
	    JspWriter out      = pageContext.getOut();
	    
	    // start building up the tag
	    out.println();
	    out.println("<TABLE BORDER=\"0\" CELLSPACING=\"0\" CELLPADDING=\"0\">");
	    
	    //print labels if they are available
	    if (!Utils.isEmpty(leftLabel) || !Utils.isEmpty(rightLabel) ) {
		out.println("<TR><TD VALIGN=\"bottom\" style=\"padding: 2px 2px 0px 0px;\">");
		out.println( Utils.noNulls(leftLabel) );
		out.println("</TD><TD VALIGN=\"bottom\" style=\"padding: 2px 2px 0px 0px;\">");
		out.println( Utils.noNulls(rightLabel) );
		out.println("</TD></TR>");
	    }

	    out.println("<TR><TD VALIGN=\"middle\" style=\"padding: 2px 2px 0px 0px;\">");

	    //add the first select list
	    out.println("<select multiple ");
	    out.println("    name=\"" + Util.quote(name + "Select") + "\"");
	    out.println("    id=\"" + Util.quote(name + "Select") + "\"");
	    out.println("    onDblClick=\"moveSelectedOptions(this, this.form." + Util.quote(name) + ", false);\"");

	    //disable the form field if disabled is set
	    if (disabled) {
		out.println("    readonly=\"readonly\"");
		out.println("    OnFocus=\"blur();\"");
		appendAttribute("style", "cursor:default;");
	    }

	    // include any attributes we've got here
	    Util.printAttributes(out, leftAttributes);

	    //if this is a required field and it is not filled out, do something...
	    if ( !Utils.isEmpty((String)req.getAttribute("error_" + name + "_error")) ) {
                out.println("    class=\"cminput_error\"");
            }
	    out.println(">");

            // actually print the <option> tags
            if (options != null) {
                Collection c = (Collection)(options.orderedKeys());
                Iterator i = c.iterator();

                while (i.hasNext()) {

		    String key;
		    String value;
		    
		    try {
			key   = (String)i.next();
			if (key == null) continue;  //do not allow null keys
			value = (String)options.get(key);
		    } catch (ClassCastException cce) {
			/* If the option contains non-Strings, give the user
			 * a more meaningful message than what he or she would get
			 * if we just propagated a ClassCastException back.
			 */
			throw new JspTagException("all members in options Map must be Strings");
		    }

                    if (value == null) value = key;   // use key if value is null

		    out.print("<option value=\"" + Util.quote(key) + "\">");
                    out.print(Util.quote(value));
                    out.println("</option>");
                }
	    }
	    // end the select tag
	    out.println("</select>");
	    out.println("</TD><TD VALIGN=\"middle\" style=\"padding: 2px 2px 0px 0px;\">");

	    //add the second select list
	    out.println("<select multiple ");
	    out.println("    name=\"" + Util.quote(name) + "\"");
	    out.println("    id=\"" + Util.quote(name) + "\"");
	    out.println("    onDblClick=\"moveSelectedOptions(this, this.form." + Util.quote(name + "Select") + ", false);\"");

	    //disable the form field if disabled is set
	    if (disabled) {
		out.println("    readonly=\"readonly\"");
		out.println("    OnFocus=\"blur();\"");
		appendAttribute("style", "cursor:default;");
	    }

	    // include any attributes we've got here
	    Util.printAttributes(out, rightAttributes);

	    //if this is a required field and it is not filled out, do something...
	    if ( !Utils.isEmpty((String)req.getAttribute("error_" + name + "_error")) ) {
                out.println("    class=\"cminput_error\"");
            }
	    out.println(">");

            // actually print the <option> tags
            if (dOpts != null) {
                Collection c = (Collection)(dOpts.orderedKeys());
                Iterator i = c.iterator();

                while (i.hasNext()) {

		    String key;
		    String value;
		    
		    try {
			key   = (String)i.next();
			if (key == null) continue;  //do not allow null keys
			value = (String)dOpts.get(key);
		    } catch (ClassCastException cce) {
			/* If the option contains non-Strings, give the user
			 * a more meaningful message than what he or she would get
			 * if we just propagated a ClassCastException back.
			 */
			throw new JspTagException("all members in default Map must be Strings");
		    }

                    if (value == null) value = key;   // use key if value is null

		    out.print("<option value=\"" + Util.quote(key) + "\">");
                    out.print(Util.quote(value));
                    out.println("</option>");
                }
	    }
	    // end the select tag
	    out.println("</select>");
	    
	    out.println("</TD></TR></TABLE>");

	    //output links to the javascript if they haven't already been added
	    if (!"true".equals(pageContext.getAttribute("doubleSelectImported"))) {

		// add reference to calendar javascript code
                out.println("<script type=\"text/javascript\" src=\"/js/optionTransfer.js\"></script>");

		//flag that the reference code has been added
		pageContext.setAttribute("doubleSelectImported","true");
	    }

	    //show the error message
	    if (showError) { 
		String errorMessage = (String)req.getAttribute(name + "_error_message");
		if (errorMessage != null && !"".equals(errorMessage) ) { 
		    out.print( "<BR><SPAN CLASS=\"input_error_msg\">" + errorMessage + "</SPAN>");
		}
	    }

    
	} catch (Exception ex) {
	    throw new JspTagException(ex.getMessage());
	}
	return SKIP_BODY;
    }
}

